/*
* Copyright (c) 2021 Talkweb Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef _TIOT_SYSDEP_API_H_
#define _TIOT_SYSDEP_API_H_

#if defined(__cplusplus)
extern "C" {
#endif

#include <stdint.h>

typedef enum {
    TIOT_SYSDEP_NETWORK_CRED_NONE,
    TIOT_SYSDEP_NETWORK_CRED_SVRCERT_CA,
    TIOT_SYSDEP_NETWORK_CRED_SVRCERT_PSK,
    TIOT_SYSDEP_NETWORK_CRED_MAX
} tiot_sysdep_network_cred_option_t;

typedef struct {
    tiot_sysdep_network_cred_option_t option;  /* 安全策略 */
    uint32_t      max_tls_fragment;
    uint8_t       sni_enabled;
    const char   *x509_server_cert;     /* 必须位于静态存储区, SDK内部不做拷贝 */
    uint32_t      x509_server_cert_len;
    const char   *x509_client_cert;     /* 必须位于静态存储区, SDK内部不做拷贝 */
    uint32_t      x509_client_cert_len;
    const char   *x509_client_privkey;  /* 必须位于静态存储区, SDK内部不做拷贝 */
    uint32_t      x509_client_privkey_len;
    char         *tls_extend_info;
} tiot_sysdep_network_cred_t;

typedef enum {
    SERVICE_SYSDEP_SOCKET_TCP_CLIENT,
    SERVICE_SYSDEP_SOCKET_TCP_SERVER,
    SERVICE_SYSDEP_SOCKET_UDP_CLIENT,
    SERVICE_SYSDEP_SOCKET_UDP_SERVER
} service_sysdep_socket_type_t;

typedef struct {
    char *psk_id;
    char *psk;
} service_sysdep_psk_t;

typedef enum {
    SERVICE_SYSDEP_NETWORK_SOCKET_TYPE,             /* 需要建立的socket类型  数据类型: (service_sysdep_socket_type_t *) */
    SERVICE_SYSDEP_NETWORK_HOST,                    /* 用于建立网络连接的域名地址或ip地址, 内存与上层模块共用  数据类型: (char *) */
    SERVICE_SYSDEP_NETWORK_BACKUP_IP,               /* 当建联DNS解析失败时, 使用此备用ip重试 */
    SERVICE_SYSDEP_NETWORK_PORT,                    /* 用于建立网络连接的端口号  数据类型: (uint16_t *) */
    SERVICE_SYSDEP_NETWORK_CONNECT_TIMEOUT_MS,      /* 建立网络连接的超时时间  数据类型: (uint32_t *) */
    SERVICE_SYSDEP_NETWORK_CRED,                    /* 用于设置网络层安全参数  数据类型: (tiot_sysdep_network_cred_t *) */
    SERVICE_SYSDEP_NETWORK_PSK,                     /* 用于配合PSK模式下的psk-id和psk  数据类型: (service_sysdep_psk_t *) */
    SERVICE_SYSDEP_NETWORK_MAX
} service_sysdep_network_option_t;

typedef struct {
    char addr[16]; /* ipv4地址点分十进制字符串, 最大长度15字节.  */
    uint16_t port; /* 端口号 */
} service_sysdep_addr_t;

/**
 * @brief 用以向SDK描述其运行硬件平台的资源如何使用的方法结构体
 */
typedef struct {
    /**
     * @brief 申请内存
     */
    void    *(*service_sysdep_malloc)(uint32_t size);
    /**
     * @brief 释放内存
     */
    void (*service_sysdep_free)(void *ptr);
    /**
     * @brief 获取当前的时间戳，SDK用于差值计算
     */
    uint64_t (*service_sysdep_time)(void);
    /**
     * @brief 睡眠指定的毫秒数
     */
    void (*service_sysdep_sleep)(uint64_t time_ms);
        /**
     * @brief 内存设置
     */
    void* (*service_sysdep_memset)(void* dest, int val, int size);
    /**
     * @brief 内存复制
     */
    void *(*service_sysdep_memcpy)(void *destin, void *source, unsigned n);
    /**
     * @brief 内存对比
     */
    int (*service_sysdep_memcmp)(const void *str1, const void *str2, unsigned n);
    /**
     * @brief 创建1个网络会话(L3层)
     */
    void    *(*service_sysdep_network_init)(void);
    /**
     * @brief 配置1个网络会话的连接参数
     */
    int32_t (*service_sysdep_network_setopt)(void *ctx, service_sysdep_network_option_t option, void *data);
    /**
     * @brief 建立1个网络会话, 作为MQTT/HTTP等协议的底层承载
     */
    int32_t (*service_sysdep_network_establish)(void *ctx);
    /**
     * @brief 从指定的网络会话上读取
     */
    int32_t (*service_sysdep_network_recv)(void *ctx, uint8_t *buffer, uint32_t len, uint32_t timeout_ms,
                                        service_sysdep_addr_t *addr);
    /**
     * @brief 在指定的网络会话上发送
     */
    int32_t (*service_sysdep_network_send)(void *ctx, uint8_t *buffer, uint32_t len, uint32_t timeout_ms,
                                        service_sysdep_addr_t *addr);
    /**
     * @brief 销毁1个网络会话
     */
    int32_t (*service_sysdep_network_deinit)(void **ctx);
    /**
     * @brief 随机数生成方法
     */
    void (*service_sysdep_rand)(uint8_t *output, uint32_t output_len);
    /**
     * @brief 创建互斥锁
     */
    void    *(*service_sysdep_mutex_init)(void);
    /**
     * @brief 申请互斥锁
     */
    void (*service_sysdep_mutex_lock)(void *mutex);
    /**
     * @brief 释放互斥锁
     */
    void (*service_sysdep_mutex_unlock)(void *mutex);
    /**
     * @brief 销毁互斥锁
     */
    void (*service_sysdep_mutex_deinit)(void **mutex);
    /**
     * @brief 任务申请
     */
    int (*service_task_create)(void *task_id, void *attr, void *(*start_rtn)(void*), void* arg);
     /**
     * @brief 任务销毁
     */
    int (*service_task_join)(void *thread, void **retval);
    /**
     * @brief 设备唯一标识
     */
    char* (*service_unique_identifier)(void);
} tiot_sysdep_portfile_t;

void tiot_sysdep_set_portfile(tiot_sysdep_portfile_t *portfile);
tiot_sysdep_portfile_t *tiot_sysdep_get_global_config(void);

#if defined(__cplusplus)
}
#endif

#endif

